/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 *
 */

import { hvigorCore, HvigorCoreNode, Project } from '@ohos/hvigor';
import { OhosLogger } from '../../utils/log/ohos-logger';

/**
 *  计算CompileArkTS依赖链上的任务
 */
export class CompileDependencyCalculator {
  private visitedTasks: Set<string> = new Set();
  private currentSubModuleNode: HvigorCoreNode | undefined = undefined;
  private _log: OhosLogger = OhosLogger.getLogger(CompileDependencyCalculator.name);

  constructor(private project: Project) {}

  /**
   * 工程下每个节点/模块进行编译任务链计算汇总
   */
  public computeAndSetCompileDependencies(): void {
    for (const subModuleNode of this.project.getSubModules().values()) {
      this.currentSubModuleNode = subModuleNode;
      const compileTasks = this.extractCompileTasks(subModuleNode);
      if (compileTasks.length === 0) {
        continue;
      }
      this.processTaskQueue([...compileTasks]);
    }

    const finalDependencies = ['clean', ...this.processVisitedTasks()];
    hvigorCore.setCompileDependArr(finalDependencies);
  }

  /**
   * 过滤得到编译任务
   * @param subModuleNode
   * @private
   */
  private extractCompileTasks(subModuleNode: HvigorCoreNode): string[] {
    const taskNames = subModuleNode.getTaskContainer().getTaskPaths();
    return taskNames.filter((name) => name.includes('CompileArkTS'));
  }

  /**
   * 广度优先汇总编译相关依赖任务
   * @param queue
   * @private
   */
  private processTaskQueue(queue: string[]): void {
    while (queue.length > 0) {
      const task = queue.shift()!;
      if (this.visitedTasks.has(task)) {
        continue;
      }
      this.visitedTasks.add(task);
      this.addTaskDependenciesToQueue(queue, task);
    }
  }

  /**
   * 依赖任务入队
   * @param queue
   * @param task
   * @private
   */
  private addTaskDependenciesToQueue(queue: string[], task: string): void {
    const dependencies = this.getSafeTaskDependencies(task);
    dependencies?.forEach((dep) => {
      if (!this.visitedTasks.has(dep)) {
        queue.push(dep);
      }
    });
  }

  /**
   * 接收异常
   * @param task
   * @private
   */
  private getSafeTaskDependencies(task: string): string[] {
    try {
      return this.currentSubModuleNode?.getTaskDepends(task)?.map((dep) => (dep.includes(':') ? dep.split(':')[1] : dep)) || [];
    } catch (e) {
      this._log.debug(`Failed to get task dependencies giving the task path: "${task}"`);
      return [];
    }
  }

  /**
   * 处理任务path得到任务名称
   * @private
   */
  private processVisitedTasks(): string[] {
    return Array.from(this.visitedTasks).map((task) => (task.includes('@') ? task.split('@')[1] : task));
  }
}
